﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using NLog;

namespace IRC
{
    public class Channel
    {
        public string Name { get; set; }
        public string Mode { get; set; }
        public string Topic { get; set; }
        public List<string> Users { get; set; }
        public string Buffer { get; set; }
    }

    public class ConnectionInfo
    {
        public string Address { get; set; }
        public int Port { get; set; }
        public string NickName { get; set; }
        public string UserName { get; set; }
        public string FullName { get; set; }
    }

    public class IrcMessage
    {
        public string Prefix { get; set; }
        public string Command { get; set; }
        public List<string> Params { get; set; }
    }

    public class IrcClient
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        private readonly TcpSocketClient _tcpSocketClient;
        private ConnectionInfo _connectionInfo;
        public Dictionary<string, Channel> Channels; 

        public IrcClient()
        {
            _tcpSocketClient = new TcpSocketClient();
            _tcpSocketClient.OnMessageReceived += ProcessIrcMessage;
            _tcpSocketClient.OnConnected += Connected;
            Channels = new Dictionary<string, Channel>();
        }

        public void Connect(ConnectionInfo connectionInfo)
        {
            _connectionInfo = connectionInfo;
            _tcpSocketClient.StartClient(connectionInfo.Address, connectionInfo.Port);
        }

        public void Connected()
        {
            var nickMessage = String.Format("NICK {0}", _connectionInfo.NickName);
            var userMessage = String.Format("USER {0} 8 * : {1}", _connectionInfo.UserName, _connectionInfo.FullName);
            SendMessage(nickMessage);
            SendMessage(userMessage);
        }        

        public IrcMessage ParseMessage(string message)
        {          
            IrcMessage msg = new IrcMessage();
            var msgSections = message.Split(' ').ToList();
            if(msgSections.Count > 0)
            {
                msg.Prefix = msgSections[0];
                msgSections.RemoveAt(0);
            }

            if (msgSections.Count > 0)
            {
                msg.Command = msgSections[0];
                msgSections.RemoveAt(0);
            }

            msg.Params = msgSections;
            return msg;
        }

        public void ProcessIrcMessage(string message)
        {
            Logger.Info(message);
            //Console.WriteLine("IrcClient: " + message);
            if (message.Contains("PING"))
                HandlePing(message);

            IrcMessage ircMessage = ParseMessage(message);
            IrcCommandProcessor cp = new IrcCommandProcessor(Channels);
            cp.ProcessMessage(ircMessage);            
        }

        public void ProcessUserMessage(string message)
        {
            Logger.Info(message);
            //TODO: Add user command processor            
        }

        private void HandlePing(string message)
        {
            var msgSections = message.Split(' ');
            _tcpSocketClient.Send("PONG " + msgSections[1]);
        }

        public void SendMessage(string message)
        {
            _tcpSocketClient.Send(message);
        }
    }
}
